namespace ScrumSprintMonitor.Modules.WorkItemMonitor.ViewModels
{
	#region #using Directives

	using System.Collections.Generic;
	using System.Linq;
	using System.Threading;

	using Infrastructure;

	using Microsoft.Practices.ServiceLocation;

	using UI.Wpf.PostSharp;
	using UI.Wpf.Properties;
	using UI.Wpf.ViewModels;

	#endregion

	[GuardDisposed]
	public class BacklogItemCountChartViewModel : SprintChartViewModelBase<IWorkItemCountPieChartData>,
	                                              IBacklogItemCountChartViewModel
	{
		static BacklogItemCountChartViewModel()
		{
			var dependsOn = Register<BacklogItemCountChartViewModel>();

			dependsOn.Call(me =>
			               {
			               	if (me.PieChartData.Any())
			               	{
			               		me.GetBacklogItemCountPieChartData(0).Value = me.ReadyForTestWork_BacklogItemCount;
			               	}
			               }).OnChanged(me => me.ReadyForTestWork_BacklogItemCount);
			dependsOn.Call(me =>
			               {
			               	if (me.PieChartData.Any())
			               	{
			               		me.GetBacklogItemCountPieChartData(2).Value = me.ActiveWork_BacklogItemCount;
			               	}
			               }).OnChanged(me => me.ActiveWork_BacklogItemCount);
			dependsOn.Call(me =>
			               {
			               	if (me.PieChartData.Any())
			               	{
			               		me.GetBacklogItemCountPieChartData(3).Value = me.NotDoneWork_BacklogItemCount;
			               	}
			               }).OnChanged(me => me.NotDoneWork_BacklogItemCount);
		}

		public BacklogItemCountChartViewModel(IServiceLocator serviceLocator, ISprintHoursChartViewModel sprintHoursChartViewModel)
			: base(serviceLocator)
		{
			this.sprintHoursChartViewModel = sprintHoursChartViewModel;
		}

		#region Private Fields

		private readonly ISprintHoursChartViewModel sprintHoursChartViewModel;

		#endregion

		#region Private Methods

		protected override void OnSprintDataInitialized()
		{
			if (PieChartData.Count == 4)
			{
				return;
			}

			PieChartData.Clear();

			PieChartData.Add(new WorkItemCountPieChartData
			                 	{
			                 		Value = ReadyForTestWork_BacklogItemCount,
			                 		StateName = Resources.WorkItemState_ReadyForTest,
			                 		TimeDimension = this.sprintHoursChartViewModel.PieChartData[0]
			                 	});
			PieChartData.Add(new WorkItemCountPieChartData
			                 	{
			                 		Value = 0.0,
			                 		StateName = string.Empty,
			                 		TimeDimension = this.sprintHoursChartViewModel.PieChartData[1]
			                 	});
			PieChartData.Add(new WorkItemCountPieChartData
			                 	{
			                 		Value = ActiveWork_BacklogItemCount,
			                 		StateName = Resources.WorkItemState_Active,
			                 		TimeDimension = this.sprintHoursChartViewModel.PieChartData[2]
			                 	});
			PieChartData.Add(new WorkItemCountPieChartData
			                 	{
			                 		Value = NotDoneWork_BacklogItemCount,
			                 		StateName = Resources.WorkItemState_NotDone,
			                 		TimeDimension = this.sprintHoursChartViewModel.PieChartData[3]
			                 	});
		}

		protected override void OnCalculateWorkItemData(IList<IWorkItemAdapter> workItems)
		{
			base.OnCalculateWorkItemData(workItems);

			int readyForTestBacklogItems = 0, activeBacklogItems = 0, notDoneBacklogItems = 0;

			var sprintBacklogItems = workItems.Where(x => x.Type == WorkItemType.SprintBacklogItem);
			Parallel.Invoke(() => readyForTestBacklogItems = sprintBacklogItems.Count(x => x.State == WorkItemState.Done),
			                () => activeBacklogItems = sprintBacklogItems.Count(x => x.State == WorkItemState.InProgress),
			                () => notDoneBacklogItems = sprintBacklogItems.Count(x => x.State == WorkItemState.NotDone));

			ReadyForTestWork_BacklogItemCount = readyForTestBacklogItems;
			ActiveWork_BacklogItemCount = activeBacklogItems;
			NotDoneWork_BacklogItemCount = notDoneBacklogItems;
		}

		private IWorkItemCountPieChartData GetBacklogItemCountPieChartData(int index)
		{
			return PieChartData[index];
		}

		#endregion

		#region Implementation of ISprintChartViewModel

		public override string Caption
		{
			get { return Resources.ChartCaption_BacklogItems; }
		}

		[Notify]
		public int ActiveWork_BacklogItemCount { get; private set; }

		[Notify]
		public int ReadyForTestWork_BacklogItemCount { get; private set; }

		[Notify]
		public int NotDoneWork_BacklogItemCount { get; private set; }

		#endregion
	}
}